#include "../server.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

void HandleClose(Channel *channel)
{
    std::cout << "fd: " << channel->Fd() << std::endl;
    // 移除事件监控
    channel->Remove();
    delete channel;
}

void HandleRead(Channel *channel)
{
    // 从fd中读取数据进行回显
    int fd = channel->Fd();
    char buffer[1024] = {0};
    ssize_t ret = recv(fd, &buffer, 1024, 0);
    if (ret > 0)
    {
        std::cout << buffer << std::endl;
    }
    else
    {
        HandleClose(channel);
    }
    // 启动写事件监控
    channel->EnableWrite();
}

void HandleWrite(Channel *channel)
{
    int fd = channel->Fd();
    std::string msg = "今天天气很好!";
    ssize_t ret = send(fd, msg.c_str(), msg.size(), 0);
    if (ret < 0)
    {
        HandleClose(channel);
    }
    // 只进行一次交互  关闭写监控
    channel->DisableWrite();
}

void HandleError(Channel *channel)
{
    HandleClose(channel);
}

void HandleEvent(Channel *channel)
{
    std::cout << " Have a Event!" << std::endl;
}

// 为新获取到的连接
void Acceptor(Channel *channe, Epoller *poller)
{
    int fd = channe->Fd();
    int newfd = accept(fd, NULL, NULL);
    // 为新连接新建一个 channel
    Channel *channel = new Channel(poller, newfd);
    // 并设置回调函数
    channel->SetReadCallBack(std::bind(HandleRead, channel));
    channel->SetWriteCallBack(std::bind(HandleWrite, channel));
    channel->SetCloseCallBack(std::bind(HandleClose, channel));
    channel->SetErrCallBack(std::bind(HandleError, channel));
    channel->SetEventCallBack(std::bind(HandleEvent, channel));
    // 启动读监控
    channel->EnableRead();
}

int main()
{
    Socket tcp_listen;
    tcp_listen.CreateServer(8500); // 默认是阻塞式
    int fd = tcp_listen.Fd();
    Epoller poller;
    // 为监听套接字 新建一个 channel 用户事件监控
    Channel *channel = new Channel(&poller, fd);
    // 设置可读事件的回调，启动可读事件的监控
    channel->SetReadCallBack(std::bind(Acceptor, channel, &poller));
    channel->EnableRead();

    // 开始监控，获取活跃连接，并执行事件
    while (true)
    {
        std::vector<Channel *> actives;
        poller.Epoll(&actives);
        for (auto &e : actives)
        {
            e->HandleEvent();
        }
    }
    return 0;
}